/*****************************************************************************
*                     Organizaci?n de Datos - 75.06                          *
*                         C?tedra Lic. Servetto                              *
*            Facultad de Ingenier?a - Universidad de Buenos Aires            *
******************************************************************************/

#include "CapaIndices.h"

#include <iostream>
#include "ArbolBMas.h"
#include "MetadataOperacion.h"
#include "../Comun/MetadataClase.h"
#include "Operacion.h"
#include "Indices.h"
#include <fstream>
#include <sstream>

using namespace std;
using namespace CapaIndices;

string IntToString(int i){
	string s;
	stringstream ss;
	ss << i;
	ss >> s;
	return s;
}

string imprimirNombreVars(list<Atributo>& Atribs){
	string Encab="";
	list<Atributo>::iterator it=Atribs.begin();
	Encab+=(*it++).Nombre;
	while (it!=Atribs.end()){
		Encab+=";" + (*it++).Nombre;
	}
	Encab+="\n";
	return Encab;
}

string imprimirRegistro(Registro& R){
	string Valores="";
	list<Atributo>::iterator it=R.Atributos.begin();
	Valores+=(*it++).Valor;
	while (it!=R.Atributos.end()){
		Valores+=";"+(*it++).Valor;
	}
	Valores+="\n";
	return Valores;
}

void ImprimirDatos(string NombreArch,list<Registro>* Registros){
	fstream ArchSalida(NombreArch.c_str(),ios_base::out);
	ArchSalida << imprimirNombreVars(Registros->begin()->Atributos);
	for (list<Registro>::iterator it=Registros->begin();it!=Registros->end();++it)
		ArchSalida << imprimirRegistro(*it) << endl;

	ArchSalida.close();	
}

void ImprimirResultados(string NombreArch,CapaIndices::Operacion* OP,string NombreArchDatos){
	fstream ArchSalida(NombreArch.c_str(),ios_base::out);
	if(OP->esSeleccion()){
		ArchSalida << Comun::ExitoConsulta << endl;
		ArchSalida << OP->getCantRegAfectados() << endl;
		//ArchSalida << "Se seleccionaron " << OP->getResultado()->size() << " Registros" << endl;
		ArchSalida << NombreArchDatos << endl;		
		//ImprimirDatos(NombreArchDatos,OP->getResultado());
	}else if(OP->esDeMetadata()){
		Atributo Atr;
		for (list<Registro>::iterator it=OP->getResultado()->begin();it!=OP->getResultado()->end();++it){
			Atr=(*it).Atributos.front();			
			ArchSalida << Atr.Valor << endl;
		}
	}else if(OP->esInsercion()){
		ArchSalida << Comun::ExitoConsulta << endl;
		ArchSalida << "Se Inserto una instancia de la clase" << endl;
	}else if(OP->esAltaClase()){
		ArchSalida << "true" << endl;
	}else{
		ArchSalida << Comun::ExitoConsulta << endl;
		ArchSalida << "Resultaron afectados " << OP->getCantRegAfectados() << " Registros" << endl;
	}
	ArchSalida.close();

}



int main(int argc, char* argv[])
{	
	MetadataOperacion* MO;
	fstream* streamLectura;
	CapaIndices::Operacion* OP;
	string NombreArch;
	
	if (argc>=2){
		for (int NroArg=1;NroArg<argc;++NroArg){

			stringstream s;
			s << "Transacciones/CapaIndices/Entrada/" << argv[NroArg] << ".txt";
			streamLectura = new fstream(s.str().c_str());

			if (streamLectura->is_open())
			{
				MO=MetadataOperacion::hidratar(*streamLectura);
				CapaIndices::Operacion* OP=MO->generarOperacion();
								
				OP->numero = atoi(argv[NroArg]);
				OP->Ejecutar();
				
				stringstream out;
				out << "Transacciones/CapaIndices/Salida/" << argv[NroArg] << ".txt";				

				stringstream datos;
				datos << "Transacciones/CapaIndices/Resultados/" << argv[NroArg] << ".csv";				
				
				ImprimirResultados(out.str(),OP,datos.str());

				streamLectura->close();
				delete streamLectura;
				delete OP;
				delete MO;
			}
			
		}
	}
	return 0;
}
		/*
		streamLectura=new fstream(argv[1]);
		//streamLectura=new fstream(archivo.str().c_str());
		if (streamLectura->is_open())
		{
			MO=MetadataOperacion::hidratar(*streamLectura);
			OP=MO->generarOperacion();
			OP->Ejecutar();

			ImprimirResultados("ResultadoOperacion.csv",OP->getResultado());

			streamLectura->close();
			delete streamLectura;
			delete OP;
			delete MO;
		}
		

	}
	
	cout << "Seguir? ";
	string seg;
	cin >> seg;
	if (seg != "Y")
		seguir = false;
	cout << endl;


	}

	return 0;
}*/
/*
int main(int argc, char* argv[])
{

	//CapaIndices::Aplicacion::Correr(cin, cout);

	MetadatosIndice* metadatos = new MetadatosIndice();

	metadatos->NombreClase ="Clase";
	metadatos->NombreArchivo ="Indice";

	metadatos->TipoDato = Polivalente;
	metadatos->Tipo = Griego;

	MetadatosAtributo* mat = new MetadatosAtributo("Id",Entero);
	MetadatosAtributo* mat1 = new MetadatosAtributo("Nombre",Cadena);
	metadatos->Claves.insert(metadatos->Claves.end(),*mat);

	metadatos->CamposRegsitro.insert(metadatos->CamposRegsitro.end(),*mat);
	metadatos->CamposRegsitro.insert(metadatos->CamposRegsitro.end(),*mat1);

	ArbolBMas* arbol = new ArbolBMas(metadatos);
	arbol->Crear();
	EstrategiaInsercion* b = new EstrategiaInsercion(arbol);

	int i = 0;

	while (i < 15)
	{
		b->Camino.clear();
		Clave* c =  new Clave();
		string ss;
		cin >> ss;
		c->ValoresBusqueda.insert(c->ValoresBusqueda.end(),ss);
		c->OtrasCondiciones = new CondicionCompuesta();

		for (IteradorDeMetadatosAtributos k = arbol->Metadata->CamposRegsitro.begin(); k!=arbol->Metadata->CamposRegsitro.end();k++)
		{
			Atributo a((*k).Nombre,ss);
			a.Tipo = (*k).Tipo;
			c->DatosAInsertar.insert(c->DatosAInsertar.end(),a);
		}

		Resultado r = b->EjecutarEstrategia(c);
		i++;
	}

	cout << "Menor a: " ;

	EstrategiaActualizacion* bus = new EstrategiaActualizacion(arbol,true);

	Clave* clave2 =  new Clave();
	string ss;
	cin >> ss;
	clave2->ValoresBusqueda.insert(clave2->ValoresBusqueda.end(),ss);
	clave2->OtrasCondiciones = new CondicionCompuesta();
	Atributo a("Nombre","Pepe");
	a.Tipo = Cadena;
	clave2->DatosAInsertar.insert(clave2->DatosAInsertar.end(),a);


	CondicionMayor* igual = new CondicionMayor();
	igual->ValorCondicion.Nombre = "Id";
	igual->ValorCondicion.Valor = ss;
	igual->ValorCondicion.Tipo = Entero;

	clave2->OtrasCondiciones->Subcondiciones.insert(clave2->OtrasCondiciones->Subcondiciones.end(),igual);

	Resultado r = bus->EjecutarEstrategia(clave2);

	//			cout << endl << "C?digo: " << r.Codigo << endl << r.mensaje << endl << " Camino: ";

	for (IteradorDePunterosANodo i = b->Camino.begin(); i!=b->Camino.end();i++)
	{
		Nodo* n = *i;
		cout << n->NodoId << " --> ";
	}

	cout << endl;
	cout << "Registro: " << endl;
	if (clave2->Resultado.size()==0)
		cout << "No encontrado." << endl;
	else
		for (IteradorDeRegistros j = clave2->Resultado.begin(); j!= clave2->Resultado.end();j++)
		{
			for (IteradorDeAtributos i = (*j).Atributos.begin(); i!= (*j).Atributos.end();i++)
				cout << (* i).Nombre << ": " << (* i).Valor << "; ";
			cout << endl;
		}

			cout << endl;

	cin >> ss;
}*/
//	return 0;
//}
/*	cin >> ss;

return 0;

namespace CapaIndices
{

void Aplicacion::Correr(istream entrada, ostream salida)
{

};

}
*/
